package org.romzzz.gwtclassifieds.client.ui;

import java.util.Date;
import java.util.List;
import org.romzzz.gwtclassifieds.client.data.CategoryBean;
import org.romzzz.gwtclassifieds.client.data.ClassifiedBean;
import org.romzzz.gwtclassifieds.client.i18n.LocalizedStrings;
import org.romzzz.gwtclassifieds.client.service.ClassifiedService;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.Field;
import com.extjs.gxt.ui.client.widget.form.FormButtonBinding;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.Radio;
import com.extjs.gxt.ui.client.widget.form.RadioGroup;
import com.extjs.gxt.ui.client.widget.form.TextArea;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.Validator;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * This popup is used to fill in all required information to create or edit a classified.
 */
public class ClassifiedPopup extends Window {
	
	/**
	 * Builds the popup without and show it automatically.
	 * 
	 * @param existingClassified the classified to update, or null if creating a new one
	 * @param updateToken the token given by the {@link ClassifiedService#checkAcces(Long, String) checkAccess} method
	 * @param categoryList the category list panel
	 * @param classifiedGrid the classified grid panel
	 */
	public ClassifiedPopup(final ClassifiedBean existingClassified, final Long updateToken, final List<CategoryBean> categoryList, final ClassifiedGrid classifiedGrid) {
		super();
		final LocalizedStrings localizedStrings = GWT.create(LocalizedStrings.class);
		setModal(true);
		setLayout(new FitLayout());
		final FormPanel form = new FormPanel();
		form.setHeaderVisible(false);
		form.setLabelWidth(100);
		form.setFieldWidth(340);
		final Radio offer = new Radio();  
		offer.setName("offer");
		offer.setBoxLabel(localizedStrings.offer());
		offer.setValue(true);
		final Radio seek = new Radio();
		seek.setName("seek");
		seek.setBoxLabel(localizedStrings.seek());
		final RadioGroup offerSeek = new RadioGroup("offerSeek");
		offerSeek.setFieldLabel(localizedStrings.type());
		offerSeek.add(offer);
		offerSeek.add(seek);
		final TextField<String> title = new TextField<String>();
		title.setFieldLabel(localizedStrings.title());
		title.setAllowBlank(false);
		final DateField date = new DateField();
		date.setValue(new Date());
		date.setAllowBlank(false);
		date.setFieldLabel(localizedStrings.date());
		final ComboBox<CategoryBean> categories = new ComboBox<CategoryBean>();
		categories.setDisplayField("value");
		categories.setFieldLabel(localizedStrings.category());
		categories.setEditable(false);
		ListStore<CategoryBean> store = new ListStore<CategoryBean>();
		store.add(categoryList);
		categories.setStore(store);
		final TextArea body = new TextArea();
		body.setHeight(300);
		body.setFieldLabel(localizedStrings.content());
		body.setAllowBlank(false);
		final TextField<String> contact = new TextField<String>();
		contact.setFieldLabel(localizedStrings.contact());
		contact.setToolTip(localizedStrings.emailOrPhone());
		contact.setAllowBlank(false);
		final TextField<String> password = new TextField<String>();
		password.setPassword(true);
		password.setFieldLabel(localizedStrings.password());
		final TextField<String> passwordConfirm = new TextField<String>();
		passwordConfirm.setPassword(true);
		passwordConfirm.setAllowBlank(false);
		passwordConfirm.setFieldLabel(localizedStrings.confirm());
		if (existingClassified == null) {
			setHeading(localizedStrings.addClassified());
			password.setAllowBlank(false);
			passwordConfirm.setAllowBlank(false);
			passwordConfirm.setValidator(new Validator() {
				public String validate(Field<?> field, String value) {
					if (value != null && value.equals(password.getValue())) {
						return null;
					}
					return localizedStrings.passwordMismatch();
				}
			});
		} else {
			setHeading(localizedStrings.editClassified());
			offer.setValue(existingClassified.isOffer().booleanValue());
			seek.setValue(!existingClassified.isOffer().booleanValue());
			title.setValue(existingClassified.getTitle());
			date.setValue(existingClassified.getDate());
			date.setReadOnly(true);
			body.setValue(existingClassified.getBody());
			categories.setValue(existingClassified.getCategory());
			contact.setValue(existingClassified.getContact());
			password.setEnabled(false);
			password.setAllowBlank(true);
			passwordConfirm.setEnabled(false);
			passwordConfirm.setAllowBlank(true);
		}
		form.add(offerSeek);
		form.add(title);
		form.add(date);
		form.add(categories);
		form.add(body);
		form.add(contact);
		form.add(password);
		form.add(passwordConfirm);
		final Button ok = new Button(localizedStrings.ok(), new SelectionListener<ButtonEvent>() {
			@Override
			public void componentSelected(ButtonEvent ce) {
				if (form.isValid()) {
					ClassifiedBean bean = new ClassifiedBean(offerSeek.getValue() == offer, title.getValue(), body.getValue(), date.getValue(), categories.getValue(), contact.getValue());
					final MessageBox box;
					if (existingClassified != null) {
						bean.setId(existingClassified.getId());
						box = MessageBox.wait(localizedStrings.pleaseWait(), null, localizedStrings.modifyingClassified());
						ClassifiedService.App.getInstance().updateClassified(bean, updateToken, classifiedGrid.getCheckedCategories(), new addUpdateCallback(classifiedGrid, box));
					} else {
						box = MessageBox.wait(localizedStrings.pleaseWait(), null, localizedStrings.addingClassified());
						ClassifiedService.App.getInstance().addClassified(bean, password.getValue(), classifiedGrid.getCheckedCategories(), new addUpdateCallback(classifiedGrid, box));
					}
					
				}
			}
		});
		form.addButton(ok);
		
		FormButtonBinding binding = new FormButtonBinding(form);
		binding.addButton(ok);
		add(form);
		
		setSize(500, 570);
		setFocusWidget(title);
		show();
	}
	
	/**
	 * This is an implementation of the {@link AsyncCallback AsyncCallback} to avoid code redundancy.
	 */
	private class addUpdateCallback implements AsyncCallback<List<ClassifiedBean>> {
		
		private ClassifiedGrid m_grid;
		private MessageBox m_waitingBox;
		
		public addUpdateCallback(final ClassifiedGrid grid, final MessageBox waitingBox) {
			m_grid = grid;
			m_waitingBox = waitingBox;
		}
		
		public void onFailure(Throwable caught) {
			LocalizedStrings localizedStrings = GWT.create(LocalizedStrings.class);
			m_waitingBox.close();
			MessageBox.alert(localizedStrings.error(), caught.toString(), null);
		}
		public void onSuccess(List<ClassifiedBean> result) {
			m_waitingBox.close();
			hide();
			m_grid.refresh();
		}
	}

}
